#include "field.h"
#include <string.h>
#include <stdio.h>

void field_delete(Field *f)
{
    CHECK_FIELD(f);
    
    free((void*)(f->name));
    free(f->array[0]);
    free(f->array);
    memset(f,0,sizeof(Field));
    free(f);
}

Field *field_create(const char *name,
                    const int   nx,
                    const int   ny)
{
    static const char fn[] = "field_create";
    
    Field *f = NULL;
    int    j;
    
    //--------------------------------------------------------------------------
    // check
    //--------------------------------------------------------------------------
    assert(name!=NULL);
    assert(nx>0);
    assert(ny>0);
    
    //--------------------------------------------------------------------------
    // allocate field
    //--------------------------------------------------------------------------
    f = (Field *) calloc(1,sizeof(Field));
    if(NULL == f)
    {
        fprintf( stderr, "%s: can't allocate struct Field for '%s'\n", fn, name);
        exit(1);
    }
    f->nx = nx;
    f->ny = ny;
    
    //--------------------------------------------------------------------------
    // allocate rows
    //-------------------------------------------------------------------------
    f->array = (double **) calloc( f->ny,sizeof(double *));
	if( NULL == f->array)
	{
        fprintf( stderr, "%s: can't allocate rows for '%s'\n", fn, name);
 		exit(1);
	}
	
	//--------------------------------------------------------------------------
	// allocate contiguous items
	//--------------------------------------------------------------------------
	f->array[0] = (double *) calloc( f->nx * f->ny, sizeof(double) );
	if( NULL == f->array[0])
	{
        fprintf( stderr, "%s: can't allocate data for '%s'\n", fn, name);
		exit(1);
	}
	
	//--------------------------------------------------------------------------
	// linking rows...
	//--------------------------------------------------------------------------
	for( j=1; j < f->ny; ++j )
	{
		f->array[j]=f->array[j-1]+f->nx;
	}
    
    //--------------------------------------------------------------------------
	// make a name
	//--------------------------------------------------------------------------
    f->name = strdup( name );
    if( NULL == name )
    {
        fprintf( stderr, "%s: can't allocate name for '%s'\n", fn, name);
		exit(1);
    }
    return f;
}

Field *field_align( const char *name, const Field *f)
{
    CHECK_FIELD(f);
    assert(name!=NULL);
    return field_create( name, f->nx, f->ny );
}


void field_set(Field        *f,
               const double  value)
{
    double **a;
    int      i,j;
    CHECK_FIELD(f);
    
    a = ARRAY_OF(f);
    for( j=0; j < f->ny; ++j )
    {
        for( i=0; i < f->nx; ++i )
        {
            a[j][i] = value;
        }
    }
    
}

void field_info(const Field *f, FILE *fp)
{
    CHECK_FIELD(f);
    assert(fp);
    fprintf(fp,"field<%s>:[%3dx%3d]\n", f->name, f->nx, f->ny);
}


